package role

import (
	"context"

	"mall/service/backend/common/i18n"
	"mall/service/backend/model"
	"mall/service/backend/rpc/internal/svc"
	"mall/service/backend/rpc/internal/utils/errorhandler"
	"mall/service/backend/rpc/types/backend"

	"github.com/zeromicro/go-zero/core/logx"
)

type RoleMenuAuthorityLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewRoleMenuAuthorityLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RoleMenuAuthorityLogic {
	return &RoleMenuAuthorityLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *RoleMenuAuthorityLogic) RoleMenuAuthority(in *backend.RoleMenuAuthorityReq) (*backend.BaseResp, error) {
	if in.RoleId > 0 && len(in.MenuIds) > 0 {
		relFilterMap := make(map[string]map[string][]any)
		relFilterMap[model.SysRoleMenuRelationshipColumns.RoleID] = map[string][]any{
			"equalTo": []any{in.RoleId},
		}
		rel, _, err := l.svcCtx.SysRole.GetRelMenuList(l.ctx, model.M{}, -1, relFilterMap)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		sysRoleRel := &model.SysRoleRel{}

		if len(rel) > 0 {
			var mids []uint64
			omidMap := make(map[uint64]struct{})
			for _, v := range rel {
				mids = append(mids, v.MenuID)
				omidMap[v.MenuID] = struct{}{}
			}

			nmidMap := make(map[uint64]struct{})
			for _, mid := range in.MenuIds {
				if _, ok := nmidMap[mid]; !ok {
					nmidMap[mid] = struct{}{}
					if _, ok := omidMap[mid]; !ok { // 增MenuID
						sysRoleRel.MenuIds = append(sysRoleRel.MenuIds, mid)
					}
				}
			}

			for _, mid := range mids {
				if _, ok := nmidMap[mid]; !ok { // 删MenuID
					sysRoleRel.DelMenuIds = append(sysRoleRel.DelMenuIds, mid)
				}
			}
		} else {
			nmidMap := make(map[uint64]struct{})
			for _, mid := range in.MenuIds {
				if _, ok := nmidMap[mid]; !ok { // 增MenuID
					nmidMap[mid] = struct{}{}
					sysRoleRel.MenuIds = append(sysRoleRel.MenuIds, mid)
				}
			}
		}

		err = l.svcCtx.SysRole.UpdateRel(l.ctx, tx, in.RoleId, sysRoleRel)
		if err != nil {
			tx.Rollback()
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		tx.Commit()
	}

	return &backend.BaseResp{
		Msg: i18n.UpdateSuccess,
	}, nil
}
